package com.zbkj.client.task;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zbkj.client.config.WebSocketSessionManager;
import com.zbkj.client.enums.WebSocketEventType;
import com.zbkj.client.service.AgentClientService;
import com.zbkj.client.service.ClientLoginService;
import com.zbkj.client.service.DigitalPersonService;
import com.zbkj.client.vo.DpVoiceCjVo;
import com.zbkj.common.model.client.digital.DpVoice;
import com.zbkj.service.service.DpVoiceService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Component
public class DpVoiceStatusUpdateTask {
    @Resource
    private ThreadPoolTaskScheduler taskScheduler;
    @Resource
    private RestTemplate restTemplate;
    @Resource
    private DpVoiceService dpVoiceService;
    @Resource
    private DigitalPersonService digitalPersonService;

    @Autowired
    private WebSocketSessionManager webSocketSessionManager;
    @Autowired
    private DpVoiceUrlUpdateTask dpVoiceUrlUpdateTask;

    @Value("${digital-person.url}")
    private String digitalPersonUrl;

    @Autowired
    private AgentClientService agentClientService;

    @Autowired
    private ClientLoginService clientLoginService;

    private final String dpVoiceDetailUrl = "/open/v1/audio_task_state";
    private final ObjectMapper objectMapper = new ObjectMapper();

    public void start(String linkId) {
        schedule(linkId, 0, 2 * 60 * 1000); // 首次2分钟后执行
    }

    private void schedule(String linkId, int retryCount, long delay) {
        taskScheduler.schedule(() -> {
            try {
                doTask(linkId, retryCount);
            } catch (Exception e) {
                log.error("定时任务-合成声音定时任务异常", e);
            }
        }, new Date(System.currentTimeMillis() + delay));
    }

    private void doTask(String linkId, int retryCount) {
        DpVoice dpVoice = dpVoiceService.lambdaQuery()
                .eq(DpVoice::getLinkId, linkId)
                .one();
        if (dpVoice == null) {
            log.warn("定时任务-未找到合成声音记录，linkId={}", linkId);
            return;
        }
        if (dpVoice.getIsDel() != null && dpVoice.getIsDel() == 1) {
            log.info("定时任务-合成声音已被删除，linkId={}", linkId);
            return;
        }
        if (dpVoice.getStatus() != null && dpVoice.getStatus() != 1) {
            //扣点
            clientLoginService.updateMerPoint(dpVoice.getUserId(),
                    dpVoice.getMerId(),
                    "addVoice",
                    dpVoice.getId(),
                    agentClientService.getMouleName("addVoice"),
                    "",
                    agentClientService.getPointByDuration("addVoice", dpVoice.getDuration()),
                    dpVoice.getDuration()
                    );

            log.info("定时任务-合成声音已更新过，linkId={}", linkId);
            return;
        }

        // 拉取蝉镜接口
        String accessToken = digitalPersonService.getAccessToken();
        String url = digitalPersonUrl + dpVoiceDetailUrl;
        HttpHeaders headers = new HttpHeaders();
        headers.set("access_token", accessToken);
        headers.setContentType(MediaType.APPLICATION_JSON);
        Map<String, Object> params = new HashMap<>();
        params.put("task_id", dpVoice.getLinkId());
        HttpEntity<Map<String, Object>> entity = new HttpEntity<>(params, headers);
        ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, entity, String.class);
        String body = response.getBody();
        if (body == null) {
            log.warn("定时任务-蝉镜返回空数据，linkId={}", linkId);
            return;
        }
        try {
            JsonNode root = objectMapper.readTree(body);
            int code = root.path("code").asInt();
            if (code != 0) {
                log.warn("定时任务-蝉镜返回code!=0，linkId={}, code={}, msg={}", linkId, code, root.path("msg").asText());
                if (retryCount < 5) {
                    log.info("合成声音未完成，1分钟后重试，linkId={}, retry={}", linkId, retryCount + 1);
                    schedule(linkId, retryCount + 1, 60 * 1000);
                }
                return;
            }
            JsonNode dataNode = root.path("data");
            if (dataNode.isMissingNode() || dataNode.isNull()) {
                log.warn("定时任务-蝉镜返回data字段为空，linkId={}", linkId);
                return;
            }
            DpVoiceCjVo cjVo = objectMapper.treeToValue(dataNode, DpVoiceCjVo.class);
            if (cjVo == null) {
                log.warn("定时任务-data字段转DpVoiceCjVo失败，linkId={}", linkId);
                return;
            }

            if (cjVo.getStatus() != 1 && dpVoice.getStatus() == 1) {
                // 需要更新
                // 更新字段
                dpVoice.setType(cjVo.getType());
                dpVoice.setStatus(cjVo.getStatus());
                //新增字段
                dpVoice.setFocusTitles(cjVo.getFocus_titles());
                // 将text数组转换为字符串
                if (cjVo.getText() != null && !cjVo.getText().isEmpty()) {
                    dpVoice.setText(String.join(" ", cjVo.getText()));
                }
                dpVoice.setSlice(cjVo.getSlice());
                dpVoice.setErrMsg(cjVo.getErrMsg());
                dpVoice.setErrReason(cjVo.getErrReason());
                dpVoice.setSubtitles(cjVo.getSubtitles());
                dpVoice.setUpdateTime(new Date());

                // 如果有full信息，更新相关字段
                if (cjVo.getFull() != null) {
                    dpVoice.setUrl(cjVo.getFull().getUrl());
                    dpVoice.setPath(cjVo.getFull().getPath());
                    dpVoice.setDuration(cjVo.getFull().getDuration());
                }

                dpVoice.setUpdateTime(new Date());
                dpVoiceService.updateById(dpVoice);
                log.info("定时任务-合成声音状态已更新，linkId={}", linkId);

                // 向用户推送ws事件
                // 2. 确定事件名称
                String eventName;
                if (cjVo.getStatus() != null && cjVo.getStatus() == 9) {
//                    eventName = "AddDpVoiceSuccess";
                    eventName = WebSocketEventType.AddDpVoiceSuccess.name();

                    //扣点
                    clientLoginService.updateMerPoint(dpVoice.getUserId(),
                            dpVoice.getMerId(),
                            "addVoice",
                            dpVoice.getId(),
                            agentClientService.getMouleName("addVoice"),
                            "",
                            agentClientService.getPointByDuration("addVoice", dpVoice.getDuration()),
                            dpVoice.getDuration()
                    );

                    // 异步上传OSS和更新数据库
                    dpVoiceUrlUpdateTask.start(dpVoice, cjVo);
                } else {
//                    eventName = "AddDpVoiceFail";
                    eventName = WebSocketEventType.AddDpVoiceFail.name();
                }

                // 3. 推送WebSocket消息给前端
                Integer userId = dpVoice.getUserId();
                if (userId != null) {
                    Map<String, Object> data = new HashMap<>();
                    data.put("id", dpVoice.getId());
                    data.put("linkId", cjVo.getId());
                    data.put("status", cjVo.getStatus());

                    Map<String, Object> message = new HashMap<>();
                    message.put("event", eventName);
                    message.put("data", data);

                    String jsonMessage = JSON.toJSONString(message);
                    webSocketSessionManager.sendMessageToUser(userId, jsonMessage);
                    log.info("向用户 {} 推送数字人语音合成状态更新: {}", userId, jsonMessage);
                }

                return;
            }

            if (cjVo.getStatus() == 1 && dpVoice.getStatus() == 1 && retryCount < 5) {
                log.info("合成声音未完成，1分钟后重试，linkId={}, retry={}", linkId, retryCount + 1);
                schedule(linkId, retryCount + 1, 60 * 1000);
            }
        } catch (Exception e) {
            log.error("定时任务-解析蝉镜返回数据异常，linkId={}", linkId, e);
        }
    }
} 